﻿using System;
using System.Text;
using System.Windows;
using System.Windows.Input;
using ApiScanner.Core;

namespace ApiScannerShell.ViewModels
{
    public abstract class TestConfigurationElementViewModel<TViewModel, TModel> : ViewModel<TViewModel, TModel>, IViewModel<TestConfigurationElement>
        where TViewModel : TestConfigurationElementViewModel<TViewModel, TModel>
        where TModel : TestConfigurationElement
    {
        public ICommand RemoveTestCommand { get; private set; }
        public ICommand ConfigureTestCommand { get; private set; }
        public ICommand SaveAndCloseCommand { get; private set; }
        public ICommand CancelAndCloseCommand { get; private set; }

        public bool IsEnabled
        {
            get { return GetValue(v => v.IsEnabled); }
            set { SetValue(v => v.IsEnabled, value); }
        }

        public TestConfigurationElementViewModel(TModel element, Action<IViewModel<TestConfigurationElement>> removeAction): base(element)
        {
            AddSimpleMapping(v => v.IsEnabled, () => null);
            
            RemoveTestCommand = new DelegateCommand(() => removeAction(this));
            ConfigureTestCommand = new DelegateCommand(Edit);
            CancelAndCloseCommand = new DelegateCommand<EditTestConfigurationView>(view =>
                                                                                       {
                                                                                           LoadValuesFromModel();
                                                                                           view.DialogResult = false;
                                                                                       });
            SaveAndCloseCommand = new DelegateCommand<EditTestConfigurationView>(Save);
        }

        private void Save(EditTestConfigurationView view)
        {
            try
            {
                SaveValuesToModel();
                view.DialogResult = true;
            }
            catch (ViewModelValidationFailedException ex)
            {
                var sb = new StringBuilder();
                sb.AppendLine("Please fix the following issues before saving the changes:");
                foreach (var validationMessage in ex.ValidationSummary)
                {
                    sb.AppendFormat("- {0}", validationMessage);
                    sb.AppendLine();
                }
                MessageBox.Show(sb.ToString(), "Validation failed", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        TestConfigurationElement IViewModel<TestConfigurationElement>.Model
        {
            get { return Model; }
        }

        public abstract string DisplayName { get; }
        public abstract string Description { get; }

        private void Edit()
        {
            var view = new EditTestConfigurationView(this);
            view.ShowDialog();
        }
    }
}